using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Serialization;
using OpenComposite.EII.Designer.SCA;
using OpenComposite.Repository.Properties;
using OpenComposite.EII.RepositoryUIs;
using WeifenLuo.WinFormsUI.Docking;
using OpenComposite.EII.Designer;
using OpenComposite.Base.Collections;

namespace OpenComposite.EII.Repository
{
	[Designer(typeof(ServiceModuleDesigner))]
	[RepositoryItem(ItemType.Composite, "service_modules", "svcmodule_id")]
	public class ServiceModule : RepositoryItemBaseEx
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the <see cref="ServiceModule"/> class.
		/// </summary>
		public ServiceModule()
			: base("svcmodule_id", "svcmodule_nm", "svcmodule_desc", "svcmodule_ntext", Resources.sNewServiceModule)
		{
			_svcmodule = null;
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="ServiceModule"/> class.
		/// </summary>
		/// <param name="bCreateNew">if set to <c>true</c> [b create new].</param>
		public ServiceModule(bool bCreateNew)
			: this()
		{
			if ( bCreateNew )
				this.CreateNew();
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="ServiceModule"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		public ServiceModule(int id)
			: this()
		{
			this.Load(id);
		}
		#endregion

		#region Properties

		#region Override
		/// <summary>
		/// Gets the type of the repository item.
		/// </summary>
		/// <value>The type of the repository item.</value>
		public override ItemType RepositoryItemType
		{
			get { return ItemType.Composite; }
		}
		/// <summary>
		/// Gets the name of the repository item type.
		/// </summary>
		/// <value>The name of the repository item type.</value>
		public override string RepositoryItemTypeName
		{
			get { return Resources.sServiceModule; }
		}
		/// <summary>
		/// Gets the repository item type description.
		/// </summary>
		/// <value>The repository item type description.</value>
		public override string RepositoryItemTypeDescription
		{
			get { return ""; }
		}

		/// <summary>
		/// Gets the image key.
		/// </summary>
		/// <value>The image key.</value>
		public override string ImageKey
		{
			get { return "capability"; }
		}
		/// <summary>
		/// Gets the selected image key.
		/// </summary>
		/// <value>The selected image key.</value>
		public override string SelectedImageKey
		{
			get { return this.ImageKey; }
		}
		/// <summary>
		/// Gets the image.
		/// </summary>
		/// <value>The image.</value>
		public override Image Image
		{
			get { return Resources.png_capability; }
		}
		/// <summary>
		/// Gets the selected image.
		/// </summary>
		/// <value>The selected image.</value>
		public override Image SelectedImage
		{
			get { return this.Image; }
		}

		/// <summary>
		/// Gets the name of the table.
		/// </summary>
		/// <value>The name of the table.</value>
		public override string TableName
		{
			get { return "service_modules"; }
		}

		/// <summary>
		/// Gets the delete question.
		/// </summary>
		/// <value>The delete question.</value>
		protected override string DeleteQuestion
		{
			get
			{
				string msg = base.DeleteQuestion;
				Workflow wf = this.Workflow;
				if ( wf != null ) {
					switch ( wf.Type ) {
						case WorkflowType.Orchestration:
							msg = string.Format(
								"This will delete the Composite \"{0}\" and the assigned Orchestration.{1}{1}" +
								"Do you want to continue?", wf.Name, Environment.NewLine);
							break;
						case WorkflowType.Business_Process:
							msg = string.Format(
								"This will delete the Composite \"{0}\" and the assigned Business Process.{1}{1}" +
								"Do you want to continue?", wf.Name, Environment.NewLine);
							break;
						case WorkflowType.Mashup:
							msg = string.Format(
								"This will delete the Composite \"{0}\" and the assigned Mashup.{1}{1}" +
								"Do you want to continue?", wf.Name, Environment.NewLine);
							break;
					}
				}
				return msg;
			}
		}

		private static List<ItemType> _LISTALLOWED =
			new List<ItemType>(new ItemType[] { ItemType.GenericFolder, ItemType.Verb });
		//new List<ItemType>(new ItemType[] { ItemType.GenericFolder, ItemType.Operation, ItemType.SCA_Export,
		//ItemType.SCA_Import, ItemType.Component, ItemType.SCA_StandaloneReference, ItemType.Selector });
		/// <summary>
		/// Gets the allowed child types.
		/// </summary>
		/// <value>The allowed child types.</value>
		public override List<ItemType> AllowedChildTypes
		{
			get { return _LISTALLOWED; }
		}
		/// <summary>
		/// Gets a value indicating whether [allow drop].
		/// </summary>
		/// <value><c>true</c> if [allow drop]; otherwise, <c>false</c>.</value>
		public override bool AllowDrop
		{
			get
			{
				return true;
			}
		}
		#endregion

		private ServiceModuleSymbol _svcmodule;
		/// <summary>
		/// Gets or sets the symbol.
		/// </summary>
		/// <value>The symbol.</value>
		public ServiceModuleSymbol Symbol
		{
			get { return _svcmodule; }
			set { _svcmodule = value; }
		}

		private SOBASymbol _sobaSymbol;
		/// <summary>
		/// Gets or sets the SOBA symbol.
		/// </summary>
		/// <value>The SOBA symbol.</value>
		public SOBASymbol SOBASymbol
		{
			get { return _sobaSymbol; }
			set { _sobaSymbol = value; }
		}
		private CompositeSymbol _compositeSymbol;
		/// <summary>
		/// Gets or sets the composite symbol.
		/// </summary>
		/// <value>The composite symbol.</value>
		public CompositeSymbol CompositeSymbol
		{
			get { return _compositeSymbol; }
			set { _compositeSymbol = value; }
		}

		/// <summary>
		/// Gets or sets the type.
		/// </summary>
		/// <value>The type.</value>
		public ServiceModuleType Type
		{
			get { return (ServiceModuleType)getInt("svcmodule_type", (int)ServiceModuleType.Composite); }
			set { setValue("Type", "svcmodule_type", (int)value); }
		}

		/// <summary>
		/// Gets or sets the workflow ID.
		/// </summary>
		/// <value>The workflow ID.</value>
		public int WorkflowID
		{
			get { return getInt("workflow_id", -1); }
			set { setValue("WorkflowID", "workflow_id", value); }
		}
		/// <summary>
		/// Gets the workflow.
		/// </summary>
		/// <value>The workflow.</value>
		public Workflow Workflow
		{
			get
			{
				Workflow wf = null;
				if ( this.WorkflowID > 0 ) {
					wf = this.RepositoryService.GetItem<OpenComposite.EII.Repository.Workflow>(this.WorkflowID);
					if ( wf != null && wf.IsDeleted )
						wf = null;
				}
				return wf;
			}
		}

		/// <summary>
		/// Gets or sets the capability ID.
		/// </summary>
		/// <value>The capability ID.</value>
		public int CapabilityID
		{
			get { return getInt("capability_id", -1); }
			set { setValue("CapabilityID", "capability_id", value); }
		}
		/// <summary>
		/// Gets or sets the capability.
		/// </summary>
		/// <value>The capability.</value>
		public Capability Capability
		{
			get
			{
				if ( this.CapabilityID > 0 ) {
					return this.RepositoryService.GetItem<Capability>(this.CapabilityID);
				} else {
					return null;
				}
			}
			set
			{
				if ( value == null ) {
					this.CapabilityID = -1;
				} else {
					this.CapabilityID = value.ID;
				}
			}
		}

		private ServiceModuleProperties _properties = null;
		/// <summary>
		/// Gets the extended properties.
		/// </summary>
		/// <value>The extended properties.</value>
		public ServiceModuleProperties ExtendedProperties
		{
			get
			{
				if ( _properties == null ) {
					_properties = getXmlSerializedObject<ServiceModuleProperties>("svcmodule_properties");
					if ( _properties == null )
						_properties = new ServiceModuleProperties();
				}
				return _properties;
			}
		}


		#endregion

		#region Methods
		/// <summary>
		/// Gets the icon.
		/// </summary>
		/// <returns></returns>
		public override Icon GetIcon()
		{
			Bitmap bmp = new Bitmap(this.Image);
			bmp.MakeTransparent(Color.Magenta);
			return Icon.FromHandle(bmp.GetHicon());
		}

		/// <summary>
		/// Shows the new item form.
		/// </summary>
		/// <param name="idRepository">The repository ID.</param>
		/// <param name="bAllowContinue">if set to <c>true</c> to allow save and continue.</param>
		/// <param name="parentItem">The parent item.</param>
		/// <param name="idDomain">The domain ID.</param>
		/// <param name="parentItemNew">The new parent item.</param>
		/// <returns></returns>
		public override DialogResult ShowNewItemForm(int idRepository, bool bAllowContinue, IRepositoryItem parentItem, ref int idDomain, out IRepositoryItem parentItemNew)
		{
			DialogResult dr = base.ShowNewItemForm(idRepository, bAllowContinue, parentItem, ref idDomain, out parentItemNew);

			if ( dr == DialogResult.OK ) {
				IRepositoryItem pi = null;
				Capability c = this.RepositoryService.GetNewItem<Capability>(false, ref pi);
				c.Name = this.Name;
				c.Save();
				this.Capability = c;
				this.Save();
			}

			return dr;
		}
		//public override DialogResult ShowNewItemForm(int idRepository, bool bAllowContinue,
		//    IRepositoryItem parentItem, ref int idDomain, out IRepositoryItem parentItemNew)
		//{
		//    FormCreateNewComposite dlg = new FormCreateNewComposite(this, bAllowContinue);
		//    dlg.DomainID = idDomain;
		//    dlg.ShowAllFolders = false;
		//    dlg.ParentItem = parentItem;
		//    DialogResult result = dlg.ShowDialog();
		//    if ( result == DialogResult.OK || result == DialogResult.Retry ) {
		//        idDomain = dlg.DomainID;
		//        parentItemNew = dlg.NewParentItem;
		//    } else {
		//        idDomain = 0;
		//        parentItemNew = null;
		//    }
		//    return result;
		//}
		//public override bool CreateNew()
		//{
		//    bool ok = base.CreateNew();
		//    if ( ok ) {
		//        IRepositoryItem parentItem = null;
		//        Capability c = this.RepositoryService.GetNewItem<Capability>(false, ref parentItem);
		//        c.Name = this.Name;
		//        c.Save();
		//        this.Capability = c;
		//    }
		//    return ok;
		//}
		/// <summary>
		/// Saves this instance.
		/// </summary>
		/// <returns></returns>
		public override bool Save()
		{
			if ( _properties != null )
				setXmlSerializedObject("ExtendedProperties", "svcmodule_properties", _properties);

			return base.Save();
		}

		/// <summary>
		/// Deletes this instance.
		/// </summary>
		/// <param name="bAsk">if set to <c>true</c> show a message to ask for deleting.</param>
		/// <returns></returns>
		public override bool Delete(bool bAsk)
		{
			DialogResult result = DialogResult.None;
			if ( bAsk ) {
				result = MessageBox.Show("Deleting this service will also delete all the capabilities within the service.", "Deleting service", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
				if ( result == DialogResult.Cancel ) return false;
				BindingListEx<Verb> verbs = this.GetVerbs();
				foreach ( Verb v in verbs ) {
					v.Delete(false);
				}
			}
			return base.Delete(false);
		}

		/// <summary>
		/// Called when [item deleting].
		/// </summary>
		protected override void OnItemDeleting()
		{
			base.OnItemDeleting();
			try {
				Workflow wf = this.Workflow;
				if ( wf != null )
					wf.DeleteInternal();
			} catch { }
		}

		/// <summary>
		/// Gets the verbs.
		/// </summary>
		/// <returns></returns>
		public BindingListEx<Verb> GetVerbs()
		{
			return Global.Data.GetRepositoryHierarchyChildRepositoryList<Verb>(this);
		}

		/// <summary>
		/// Copies this instance.
		/// </summary>
		/// <param name="deep"><c>true</c> to recursively copy the item and all subitems;
		/// <c>false</c> to copy only the item itself.</param>
		/// <returns>The copied item.</returns>
		public override IRepositoryItem Copy(bool deep)
		{
			return this.CopyInternal(deep, null, null);
		}
		internal ServiceModule CopyInternal(bool deep,
			Dictionary<int, int> mapVerbsOldNew, Dictionary<int, int> mapBObjsOldNew)
		{
			ServiceModule copy = new ServiceModule(true);
			copy.InitializeServiceProvider(this);
			this.CopyDataRowToTarget(copy);
			foreach ( var verb in GetVerbs() ) {
				if ( mapVerbsOldNew != null ) {
					if ( !mapVerbsOldNew.ContainsKey(verb.ID) ) {
						Verb copyVerb = verb.CopyInternal(deep, mapBObjsOldNew);
						copyVerb.CapabilityID = -1;
						copyVerb.Save();
						mapVerbsOldNew.Add(verb.ID, copyVerb.ID);
						Global.Data.AddRepositoryHierarchy(copy, copyVerb, Global.Status.CurrentRepositoryId);
					}
				} else {
					Verb copyVerb = verb.Copy(deep) as Verb;
					Global.Data.AddRepositoryHierarchy(copy, copyVerb, Global.Status.CurrentRepositoryId);
				}
			}
			return copy;
		}
		#endregion Methods

		#region Class: ServiceModuleProperties
		[Serializable]
		[XmlRoot(Namespace = "http://www.OpenComposite.com/Repository")]
		[XmlType(Namespace = "http://www.OpenComposite.com/Repository")]
		public class ServiceModuleProperties
		{
			#region Initialization
			/// <summary>
			/// Initializes a new instance of the <see cref="ServiceModuleProperties"/> class.
			/// </summary>
			public ServiceModuleProperties()
			{
				_pathDeploy = null;
				_buildType = WorkflowBuildType.WCF_IIS;

				_exposedVerbOperation = new Dictionary<int, int>();
			}
			#endregion

			#region Properties
			private string _pathDeploy;
			/// <summary>
			/// Gets or sets the deploy path.
			/// </summary>
			/// <value>The deploy path.</value>
			public string DeployPath
			{
				get { return _pathDeploy; }
				set { _pathDeploy = value; }
			}
			private WorkflowBuildType _buildType;
			/// <summary>
			/// Gets or sets the type of the build.
			/// </summary>
			/// <value>The type of the build.</value>
			public WorkflowBuildType BuildType
			{
				get { return _buildType; }
				set { _buildType = value; }
			}

			private Dictionary<int, int> _exposedVerbOperation = null;
			/// <summary>
			/// Gets the exposed verb operation.
			/// </summary>
			/// <value>The exposed verb operation.</value>
			[XmlIgnore]
			public Dictionary<int, int> ExposedVerbOperation
			{
				get { return _exposedVerbOperation; }
			}
			/// <summary>
			/// Gets or sets the exposed verb operation array.
			/// </summary>
			/// <value>The exposed verb operation array.</value>
			public string[] ExposedVerbOperationArray
			{
				get
				{
					string[] strs = new string[_exposedVerbOperation.Count];
					int i = 0;
					foreach ( KeyValuePair<int, int> keyval in _exposedVerbOperation ) {
						strs[i] = string.Format("{0};{1}", keyval.Key, keyval.Value);
						i++;
					}
					return strs;
				}
				set
				{
					if ( _exposedVerbOperation == null ) {
						_exposedVerbOperation = new Dictionary<int, int>();
					} else {
						_exposedVerbOperation.Clear();
					}
					foreach ( string str in value ) {
						string[] keyval = str.Split(';');
						if ( keyval != null && keyval.Length == 2 ) {
							int iKey, iVal;
							if ( int.TryParse(keyval[0], out iKey) && int.TryParse(keyval[1], out iVal) ) {
								_exposedVerbOperation.Add(iKey, iVal);
							}
						}
					}
				}
			}


			#endregion
		}
		#endregion
	}

	public enum ServiceModuleType
	{
		Composite = ItemType.Composite,
		SOBA = ItemType.SOBA
	}

	#region Class: ServiceModuleDesigner : Base Class: RepositoryItemDesigner
	internal class ServiceModuleDesigner : RepositoryItemDesigner
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="ServiceModuleDesigner"/> class.
		/// </summary>
		public ServiceModuleDesigner()
			: base()
		{
		}

		/// <summary>
		/// Gets a value indicating whether this instance has controllers.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance has controllers; otherwise, <c>false</c>.
		/// </value>
		public override bool HasControllers
		{
			get { return true; }
		}
		/// <summary>
		/// Gets the controllers.
		/// </summary>
		/// <param name="parentController">The parent controller.</param>
		/// <returns></returns>
		public override object[] GetControllers(IController parentController)
		{
			RepositoryService repSrv = GetService<RepositoryService>();
			DockPanel dp = GetService<DockPanel>();

			if ( repSrv == null ) throw new NullReferenceException("Missing RepositoryService.");

			IController ctrler = repSrv.CreateDesignControllerForRepositoryController(
				dp, this.RepositoryItem, parentController);
			UCGenerateService ucGenSvc = new UCGenerateService();
			ucGenSvc.Initialize(this.RepositoryItem);

			return new object[] { ctrler, ucGenSvc };
		}
	}
	#endregion
}
